package game.environments;

import interfaces.IPaintable;
import interfaces.IUpdatable;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.ImageIcon;
import sprites.NonResponsiveSprite;
import sprites.ResponsiveSprite;
import sprites.Sprite;


public class GameEnvironment {

    private List<IPaintable> myPaintables;
    private List<IUpdatable> myUpdatables;
    private List<NonResponsiveSprite> myNonRespSprites;
    private List<ResponsiveSprite> myRespSprites;
    private Image bgImage;
    private int winningScore;
    private String mySplashLoc;
    private Image mySplashImg;
    
    private final String DEFAULT_IMAGE_LOC = "/resources/defaultSplash.gif";

    public GameEnvironment () {
        myPaintables = new ArrayList<IPaintable>();
        myUpdatables = new ArrayList<IUpdatable>();
        myNonRespSprites = new ArrayList<NonResponsiveSprite>();
        myRespSprites = new ArrayList<ResponsiveSprite>();
        winningScore=10;
        mySplashLoc = DEFAULT_IMAGE_LOC;
        ImageIcon ii = new ImageIcon(this.getClass().getResource(mySplashLoc));
        mySplashImg = ii.getImage();
    }

    /**
     * Called by each step of timer, multiple times per second.
     * 
     * 
     * @param dt very small unit of time that elapsed
     */
    public void update (double dt) {
        for (IUpdatable updatable : myUpdatables) {
            updatable.update();
        }

        checkForCollisions();
        cleanGameEntities(myUpdatables);
        cleanGameEntities(myNonRespSprites);
        cleanGameEntities(myRespSprites);
        cleanGameEntities(myPaintables);
    }

    public void cleanGameEntities (List dirtyList) {
        Iterator iter = dirtyList.iterator();
        while (iter.hasNext()) {
            if (!((IUpdatable) iter.next()).isValid()) {
                iter.remove();
            }
        }
    }

    public void keyInputPort (KeyEvent e) {
        for (ResponsiveSprite rs : myRespSprites) {
            if (e != null) {
                rs.keyInputPort(e, this);

            }
        }
    }

    public Iterator<IPaintable> getPaintables () {
        return myPaintables.iterator();
    }

    // Set the background for this level
    public void setBackground (String imgLoc) {
        ImageIcon ii = new ImageIcon(this.getClass().getResource(imgLoc));
        bgImage = ii.getImage();
    }

    public Image getBackground () {
        return bgImage;
    }

    // Set the winning score of the level to be reached to finish the level
    public void setWinningScore (int score) {
        winningScore = score;
    }

    public int getWinningScore () {
        return winningScore;
    }

    /**
     * iterates through all responsive sprites(presumably all the "good" guys,
     * and grabs indiv score
     * note: score gets incremented whenever it kills, gets coins, etc (inside
     * collision handler)
     * 
     * @return
     */
    public int getCurrentScore () {
        int currentScore = 0;
        for (ResponsiveSprite rs : myRespSprites) {
            currentScore += rs.getHP();
        }
        return currentScore;
    }

    // Update list of sprites in the game level--either method overloading, or
    // simply attempt to add to all lists or relfection. not to sure what best
    // design practice
    public void add (ResponsiveSprite s) {
        myPaintables.add(s);
        myUpdatables.add(s);
        myRespSprites.add(s);
    }

    public void add (NonResponsiveSprite s) {
        myPaintables.add(s);
        myUpdatables.add(s);
        myNonRespSprites.add(s);
    }

    // Check for collisions between Sprites
    public void checkForCollisions () {
        List<Sprite> sprites = new ArrayList<Sprite>();
        sprites.addAll(myNonRespSprites);
        sprites.addAll(myRespSprites);

        for (int i = 0; i < sprites.size(); i++) {
            Sprite sprite1 = sprites.get(i);
            for (int j = i + 1; j < sprites.size(); j++) {
                Sprite sprite2 = sprites.get(j);
                if (sprite1.getRect().intersects(sprite2.getRect())) {
                    sprite1.collisionHandle(sprite2);
                    sprite2.collisionHandle(sprite1);
                }
            }
        }

    }

    public boolean isOver () {
        return (getCurrentScore() >= getWinningScore())
               || (myUpdatables.size() <= 1) || (getCurrentScore()<=0);

    }

    public Image getSplashScreen () {
        // TODO Auto-generated method stub
        return mySplashImg;
    }
}
